﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace ArgusLib.Threading
{
	public class ThreadState
	{
		public bool CancelRequested { get; private set; }
		public object[] Arguments { get; private set; }
		public Thread OwnerThread { get; private set; }

		public bool IsSuspended { get; private set; }

		private object _lock;
		private ManualResetEvent waitHandle;

		private ThreadState()
		{
			this._lock = new object();
			//this.Result = null;
			this.CancelRequested = false;
			//this.Cancelled = false;
			this.OwnerThread = Thread.CurrentThread;
			this.waitHandle = new ManualResetEvent(true);
		}

		public ThreadState(params object[] arguments)
			: this()
		{
			this.Arguments = arguments;
		}

		public void RequestCancel()
		{
			if (this.CancelRequested == true)
				return;
			this.CancelRequested = true;
			lock (this._lock)
			{
				if (this.IsSuspended == true)
				{
					this.waitHandle.Set();
					this.IsSuspended = false;
				}
			}
		}

		public void Suspend()
		{
			if (this.OwnerThread != Thread.CurrentThread)
				throw new Exception("Only the owner thread may call suspend.");
			lock (this._lock)
			{
				this.waitHandle.Reset();
				this.IsSuspended = true;
			}
		}

		public void Resume()
		{
			if (this.OwnerThread != Thread.CurrentThread)
				throw new Exception("Only the owner thread may call resume.");
			lock (this._lock)
			{
				this.waitHandle.Set();
				this.IsSuspended = false;
			}
		}

		public void WaitForResumption()
		{
			if (this.OwnerThread == Thread.CurrentThread)
				throw new Exception("The thread which created the object cannot wait. (Deadlock)");
			this.waitHandle.WaitOne();
		}
	}
}
